package cn.virens.common.boot.provider.apijson;

import apijson.Log;
import apijson.MethodAccess;
import apijson.RequestMethod;
import apijson.orm.AbstractSQLConfig;
import apijson.orm.AbstractVerifier;
import cn.virens.common.boot.provider.apijson.autoconfig.ApijsonProperties;
import cn.virens.common.util.exception.APIException;
import io.mybatis.provider.Entity.Table;
import org.dromara.hutool.core.collection.CollUtil;
import org.springframework.beans.factory.InitializingBean;

import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Consumer;

public class VirAPIJSONCreatorSimple implements VirAPIJSONCreator, InitializingBean {
    protected final ApijsonProperties properties;
    protected final DataSource mDataSource;

    public VirAPIJSONCreatorSimple(DataSource mDataSource, ApijsonProperties properties) {
        this.mDataSource = mDataSource;
        this.properties = properties;
    }

    @Override
    public APIJSONParser createParser() throws APIException {
        return new APIJSONParser(mDataSource, properties);
    }

    public static Map<RequestMethod, String[]> accessMap(MethodAccess access) throws APIException {
        HashMap<RequestMethod, String[]> map = new HashMap<>();

        map.put(RequestMethod.DELETE, access.DELETE());
        map.put(RequestMethod.HEADS, access.HEADS());
        map.put(RequestMethod.HEAD, access.HEAD());
        map.put(RequestMethod.GETS, access.GETS());
        map.put(RequestMethod.POST, access.POST());
        map.put(RequestMethod.GET, access.GET());
        map.put(RequestMethod.PUT, access.PUT());

        return map;
    }

    /**
     * 创建表关联权限
     */
    private static void put(Class<?> clazz, MethodAccess annotation) throws APIException {
        AbstractVerifier.ACCESS_MAP.put(clazz.getSimpleName(), accessMap(annotation));
    }

    /**
     * 创建表关联关系
     */
    private static void put(Class<?> clazz, Table table) throws APIException {
        AbstractSQLConfig.TABLE_KEY_MAP.put(clazz.getSimpleName(), table.value());
    }

    @Override
    public void putTable(Class<?> clazz) throws APIException {
        notNull(clazz.getAnnotation(MethodAccess.class), a -> put(clazz, a));
        notNull(clazz.getAnnotation(Table.class), a -> put(clazz, a));
    }

    private <T> void notNull(T t, Consumer<T> consumer) {
        if (t != null) consumer.accept(t);
    }

    @Override
    public void afterPropertiesSet() throws APIException {
        if (CollUtil.isNotEmpty(properties.getClasses())) {
            for (var cls : properties.getClasses()) {
                this.putTable(cls);
            }
        }

        // 设置是否开启调试模式
        Log.DEBUG = properties.getDebug();
    }
}
